package com.irdstudio.efp.rule.service.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.kie.api.KieBase;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieSession;
import org.kie.internal.KnowledgeBase;
import org.kie.internal.KnowledgeBaseFactory;
import org.kie.internal.builder.KnowledgeBuilder;
import org.kie.internal.builder.KnowledgeBuilderError;
import org.kie.internal.builder.KnowledgeBuilderErrors;
import org.kie.internal.builder.KnowledgeBuilderFactory;
import org.kie.internal.io.ResourceFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * 动态创建drools
 * 
 * @author Cytus_
 * @since 2018年6月2日 上午10:48:14
 * @version 1.0
 *
 */
@SuppressWarnings("deprecation")
public class DynamicExecuteDroolsFactory {
    
    private static Logger logger = LoggerFactory.getLogger(DynamicExecuteDroolsFactory.class);
    
    private static Map<String, KieBase> dynamicKBaseMap = new ConcurrentHashMap<String, KieBase>();
    
    private final static DynamicExecuteDroolsFactory _INSTANCE = DynamicExecuteDroolsFactoryHandler.factory;
    
    private static class DynamicExecuteDroolsFactoryHandler {
        private static final DynamicExecuteDroolsFactory factory = new DynamicExecuteDroolsFactory();
    }
    
    private DynamicExecuteDroolsFactory () {}
    
    public static DynamicExecuteDroolsFactory getFactory() {
        return _INSTANCE;
    }
    
    public KieSession createKieSession(String key, String dynamicDroolsStr) throws Exception {
        findOrCreate(key, dynamicDroolsStr);
        return dynamicKBaseMap.get(key).newKieSession();
    }

    
    private void findOrCreate(String key, String dynamicDroolsStr) throws Exception {
        if (!dynamicKBaseMap.containsKey(key)) {
            createKieBase(key, dynamicDroolsStr);   
        }
    }
    
    private void createKieBase(String key, String dynamicDroolsStr) throws Exception {
        try {
            KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder();  
            //装入规则，可以装入多个  
            kb.add(ResourceFactory.newByteArrayResource(dynamicDroolsStr.getBytes("utf-8")), ResourceType.DRL);  
              
            KnowledgeBuilderErrors errors = kb.getErrors();  
            List<String> errorMsg = new ArrayList<String>();
            for (KnowledgeBuilderError error : errors) {  
                logger.error(error.getMessage());
                errorMsg.add(error.getMessage() +"\r\n");
            }  
            if (!errorMsg.isEmpty()) {
                throw new Exception(errorMsg.toString());
            }
            KnowledgeBase kBase = KnowledgeBaseFactory.newKnowledgeBase();  
            kBase.addKnowledgePackages(kb.getKnowledgePackages());  
            dynamicKBaseMap.put(key, kBase);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw e;
        }
    }
    
    public boolean exist(String key) {
        return dynamicKBaseMap.containsKey(key);
    }
    
    public void rebuildRule(String key, String rule) throws Exception {
        if (dynamicKBaseMap.containsKey(key)) {
            try {
                synchronized (dynamicKBaseMap) {
                    dynamicKBaseMap.remove(key);
                    createKieBase(key, rule);
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                dynamicKBaseMap.notify();
                throw e;
            }
        }
    }
    
}
